#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>

#define SIZE_1M 1024*1024
#define SIZE_10M 10*1024*1024
#define SIZE_100M 100*1024*1024

int main(int argc, char const *argv[])
{
    //参数数量判断
    if(argc != 3){
        printf("Usage: %s <src源文件> <dst目标文件>\n", argv[0]);
        return -1;
    }

    //打开源文件
    int fd1 = open(argv[1], O_RDONLY);
    if(fd1 == -1){
        perror("打开源文件失败!\n");
        return -1;
    }

    //打开目标文件
    int fd2 = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if(fd2 == -1){
        perror("打开目标文件失败\n");
        return -1;
    }

    //计算目标文件大小
    lseek(fd2, 0, SEEK_END);//找到文件末尾
    long file_size = lseek(fd2, 0, SEEK_CUR);//计算偏移量，即文件大小
    lseek(fd2, 0, SEEK_SET);//将光标移回开头

    //计算缓冲区大小
    long buf_size;
    if(file_size < SIZE_1M)buf_size = SIZE_1M;
    else if(file_size < 10*SIZE_100M)buf_size = SIZE_10M;
    else buf_size = SIZE_100M;

    //设置缓冲区
    char *buf = malloc(buf_size);
    while(1){
        int read_size = read(fd1, buf, buf_size);
        //读文件失败
        if(read_size < 0){
            printf("读文件失败!\n");
            return -1;
        }
        //读文件完成
        if(read_size == 0){
            printf("拷贝完成!\n");
            return 0;
        }
        int current = 0;
        while(read_size > 0){
            int write_size = write(fd2, buf + current, read_size);
            if(write_size < 0){
                printf("写文件失败!\n");
                return -1;
            }
            read_size -= write_size;
            current += write_size;
        }
    }
    close(fd1);
    close(fd2);
    free(buf);
    return 0;
}
